
typedef unsigned short     int uint16_t;
typedef unsigned           int uint32_t;
#define     __IO    volatile
	
#define PERIPH_BASE           ((uint32_t)0x40000000)
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)

#define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
#define GPIOC               	(GPIOC_BASE)
#define GPIOC_CRH							(GPIOC+0x04)// 21 22   :00000000 00110000 00000000 00000000 		0x00300000
#define GPIOC_ODR							(GPIOC+0x0C)// 13			:00000000 00000000 00100000 00000000 		0x00002000

#define AHBPERIPH_BASE        (PERIPH_BASE + 0x20000)
#define RCC_BASE              (AHBPERIPH_BASE + 0x1000)
#define RCC                 	(RCC_BASE)
#define RCC_APB2ENR						(RCC+0x18)// 5				:00000000 00000000 00000000 00010000	 	0x00000010
#define RCC_CR								(RCC+0x00)
#define RCC_CFGR							(RCC+0x04)

#define FLASH_R_BASE          (AHBPERIPH_BASE + 0x2000)
#define FLASH               	(FLASH_R_BASE)
#define FLASH_ACR             (FLASH+0x00)

//HCLK=PLLCLK=SYSCLK=P2CLK=P1CLK*2=ADCCLK*2=TIMCLK=USBCLK*2/3
void RCC_init(uint16_t PLL)//输入PLL的倍频值2-16倍频
{
	uint32_t temp=0;  
	// 10000对应32位中16位，HSEON位，置为1代表使能HSEON时钟
	*((uint32_t *)RCC_CR) |= 0x00010000;  // 外部高速时钟使能HSEON
	// 17位是HSEON时钟使能成功位，只有使能之后才是1，这个位由系统设置，程序只能读取
	while(!( *((uint32_t *)RCC_CR) >>17));// 等待外部时钟就绪
	// 400对应PPRE1位置，二进制0100 0000 0000，10~8位数据是100
	// 0xx: HCLK not divided
	// 100: HCLK divided by 2
	// 101: HCLK divided by 4
	// 110: HCLK divided by 8
	// 111: HCLK divided by 16
	// 这里设置为001代表HCLK divided by 2，即时钟源分频2倍给PLL作为时钟，例如默认HSI是8MHz，分给PLL就是4MHz
	// ABP1时钟倍频为2，ABP2分频为1（不变），AHB也是分频为1，这里led灯是在APB2总线（时钟）下面，所以之类分频数是1
	// 为什么ABP1是重要分频2，而ABP2则不需要呢？这个是因为ABP1的总线时钟速度比系统时钟慢一倍，而ABP2的时钟总线
	// 则和系统时钟一致，这个就是为什么ABP2上面都是挂在高速部件，而ABP1则是慢速的
	// 这里注意：虽然0x400显式设置了APB2为2，但是其实这波操作把CFGR所有的相关为都设置了，包括APB2为不分频
	// 然后在后面的代码中再使能APB2，其实APB1没有被使能，设置为2倍分频并没有起什么作用
	*((uint32_t *)RCC_CFGR) = 0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
	//*((uint32_t *)RCC_CFGR) = 0X00001000;
	
	// 如果这里指定了9倍频，那么因为分频数指定为1，那么时钟源的提供倍频时钟就等于PLL时钟
	// 比如HSI默认是8M，那么9倍频之后是72MHz，PLL的时钟频率就是72MHz
	// 减去2，这一步操作是因为在PULMUL4位定义中都是倍频数-1，比如9倍倍频对应0111（十进制数字7）
	PLL -= 2;
	
	// 左移18位，到了PULMUL位
	// PLL倍频9，实际寄存器写入为0111，即7
	// 这里有一个很重要的点就是倒置数据，比如7<<18之后是0001 1100 0000 0000 0000 0000
	// 从18位开始数据位开始，从低到高位依次是0111，和文档进行对应；就是按照从左到右进行对照
	*((uint32_t *)RCC_CFGR) |= PLL<<18;   
	
	// 0: HSI oscillator(振荡器) clock / 2 selected as PLL input clock
	// 1: HSE oscillator clock selected as PLL input clock
	*((uint32_t *)RCC_CFGR) |= 1<<16;     //PLL输入设置，设置为PLL输入，写1

	// FLASH_ACR，前三位是用来设置时钟周期访问Flash1的频率，因为这次倍频目标是72MHz，所以这里采用010（2）
	// 000 Zero wait state, if 0 < SYSCLK≤ 24 MHz
	// 001 One wait state, if 24 MHz < SYSCLK ≤ 48 MHz
	// 010 Two wait states, if 48 MHz < SYSCLK ≤ 72 MHz
	// 之所以需要设置FLASH延时，是因为程序都是从Flash里面取的；CPU取用速度（系统时钟）需要和Flash进行同步
	*((uint32_t *)FLASH_ACR)|=0x2;     		//FLASH 延时设置
	*((uint32_t *)RCC_CR) |= 0x01000000;  //PLLON，使能PLL
	while(!(*((uint32_t *)RCC_CR) >> 25));//等待PLL锁定
	// 00: HSI selected as system clock
	// 01: HSE selected as system clock
	// 10: PLL selected as system clock
	// 11: not allowed
	// 这里使用10，即PLL作为系统时钟
	*((uint32_t *)RCC_CFGR) |= 0x00000002;
	while(temp != 0x02) //等待PLL系统时钟设置成功
	{  
		temp = *((uint32_t *)RCC_CFGR) >> 2;//取出判断系统设置准备位
		temp &= 0x03;
	}   
}

void delay(unsigned int time)
{    
   unsigned int i=0;  
   while(time--)
   {
      i=10000000;
      while(i--) ;    
   }
}


//int main_raw(void)
int main(void)
{
	//RCC_init(9);
	
	*((uint32_t *)RCC_APB2ENR)	|= 0x00000010;
	*((uint32_t *)GPIOC_CRH)		|= 0x00300000;
	*((uint32_t *)GPIOC_ODR)		|= 0x00002000;
	
	while(1)
	{
		//先清除要操作的相应寄存器的位
		*((uint32_t *)GPIOC_ODR)	&= ~(1<<13);
		//再赋值
		*((uint32_t *)GPIOC_ODR)	|= 0x00000000;
		
		delay(3);
		
		//灭
		*((unsigned int *)GPIOC_ODR) &= ~(1<<13);
		*((unsigned int *)GPIOC_ODR) |= 0x00002000;
		
		delay(1);
	}
	
	//return 0;
}

// int main(void){
// 	delay(1);
// 	delay(1);
// }
